/*
    *@param	[once_control]  :这是一个 pthread_once_t 类型指针，在调用 pthread_once()函数之前，我们需要定义了一个 pthread_once_t 类型的静态变量，调用 pthread_once()时参数 once_control 指向该变量。
                            通常在定义变量时会使用 PTHREAD_ONCE_INIT 宏对其进行初始化,
                            其初值不是 PTHREAD_ONCE_INIT，pthread_once()的行为将是不正常的.

    *@param	[retval]        :一个函数指针，参数 init_routine 所指向的函数就是要求只能被执行一次的代码段，
                            pthread_once()函数内部会调用 init_routine()，即使 pthread_once()函数会被多次执行，但它能保证 init_routine()仅被执行一次。
 */
// int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

#define PTHREAD_SIZE 5

static pthread_once_t once_control = PTHREAD_ONCE_INIT;

static void initialize_once(void)
{
    printf("被线程ID<%ld>调用\n", pthread_self());
}

static void func(void)
{
    pthread_once(&once_control, initialize_once); //执行一次性初始化函数
    printf("函数 func 执行完毕.\n");
}

static void *new_thread_start(void *arg)
{
    printf("第%d号线程，线程ID<%ld>\n", *((int *)arg), pthread_self());

    func();

    pthread_exit(NULL);
}

int main(void)
{
    pthread_t tid[PTHREAD_SIZE];

    int pthread_number[PTHREAD_SIZE] = {1, 2, 3, 4, 5};

    int i;

    int ret;

    //申请5个线程
    /*这 5 个线程使用同一个 start 函数 new_thread， 该函数中定义了局部变量 number 和 tid 以及 arg 参数，意味着这 5
    个线程的线程栈中都各自为这些变量分配了内存空间，任何一个线程修改了 number 或 tid 都不会影响其它线程。*/
    for (i = 0; i < PTHREAD_SIZE; i++)
    {
        ret = pthread_create(&tid[i], NULL, new_thread_start, (void *)&pthread_number[i]);
        if (ret)
        {
            fprintf(stderr, "%d pthread_create error:%s\n", i, strerror(ret));
            exit(-1);
        }
    }

    //回收5个线程
    for (i = PTHREAD_SIZE - 1; i >= 0; i--)
    {
        ret = pthread_join(tid[i], NULL);
        if (ret)
        {
            fprintf(stderr, "%d pthread_join error:%s\n", i, strerror(ret));

            exit(-1);
        }
    }

    exit(0);
}